home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / mosmllib / BasicIO.sml < prev    next >
Encoding:
Text File  |  1996-07-03  |  7.5 KB  |  260 lines  |  [TEXT/R*ch]

  1. (* BasicIO.sml *)
  2.  
  3. prim_val create_string_ : int -> string = 1 "create_string";
  4. prim_val nth_char_ : string -> int -> char = 2 "get_nth_char";
  5. prim_val set_nth_char_ : string -> int -> char -> unit = 3 "set_nth_char";
  6. prim_val blit_string_ :
  7.   string -> int -> string -> int -> int -> unit = 5 "blit_string";
  8.  
  9. fun sub_string_ s start len =
  10.   let val res = create_string_ len
  11.   in blit_string_ s start res 0 len; res end
  12. ;
  13.  
  14. (* Caml Light "channels" *)
  15.  
  16. prim_type in_channel and out_channel;
  17.  
  18. prim_val open_descriptor_in : int -> in_channel = 1 "open_descriptor";
  19.         (* [open_descriptor_in fd] returns a buffered input channel
  20.            reading from the file descriptor [fd]. The file descriptor [fd]
  21.            must have been previously opened for reading, else the behavior is
  22.        undefined. *)
  23.  
  24. prim_val open_descriptor_out : int -> out_channel = 1 "open_descriptor";
  25.         (* [open_descriptor_out fd] returns a buffered output channel
  26.            writing to the file descriptor [fd]. The file descriptor [fd]
  27.            must have been previously opened for writing, else the behavior is
  28.        undefined. *)
  29.  
  30. prim_val input_char_ : in_channel -> char = 1 "input_char"
  31.         (* Read one character from the given input channel.
  32.            Raise [Size] if there are no more characters to read. *)
  33.  
  34. prim_val caml_seek_in : in_channel -> int -> unit = 2 "seek_in"
  35.         (* [seek_in chan pos] sets the current reading position to [pos]
  36.            for channel [chan]. *)
  37.  
  38. prim_val caml_pos_in : in_channel -> int = 1 "pos_in";
  39.         (* Return the current reading position for the given channel. *)
  40.  
  41. prim_val caml_close_in : in_channel -> unit = 1 "close_in"
  42.         (* Close the given channel. Anything can happen if any of the
  43.            above functions is called on a closed channel. *)
  44.  
  45. type file_perm = int;
  46.  
  47. datatype open_flag =
  48.     O_RDONLY                       (* `open' read-only *)
  49.   | O_WRONLY                       (* `open' write-only *)
  50.   | O_RDWR                         (* `open' for reading and writing *)
  51.   | O_APPEND                       (* `open' for appending *)
  52.   | O_CREAT                        (* create the file if nonexistent *)
  53.   | O_TRUNC                        (* truncate the file to 0 if it exists *)
  54.   | O_EXCL                         (* fails if the file exists *)
  55.   | O_BINARY                       (* `open' in binary mode *)
  56.   | O_TEXT                         (* `open' in text mode *)
  57. ;
  58.  
  59. prim_val sys_open :
  60.   string -> open_flag list -> file_perm -> int = 3 "sys_open"
  61.         (* Open a file. The second argument is the opening mode.
  62.            The third argument is the permissions to use if the file
  63.            must be created. The result is a file descriptor opened on the
  64.            file. *)
  65. prim_val sys_close :
  66.   int -> unit = 1 "sys_close"
  67.         (* Close a file descriptor. *)
  68.  
  69. val caml_std_in  = open_descriptor_in 0
  70. and caml_std_out = open_descriptor_out 1
  71. and caml_std_err = open_descriptor_out 2
  72. ;
  73.  
  74. (* Moscow ML streams *)
  75.  
  76. type instream  = { closed: bool, ic: in_channel } ref;
  77. type outstream = { closed: bool, oc: out_channel } ref;
  78.  
  79. val std_in  : instream  = ref { closed=false, ic=caml_std_in }
  80. and std_out : outstream = ref { closed=false, oc=caml_std_out }
  81. and std_err : outstream = ref { closed=false, oc=caml_std_err }
  82. ;
  83.  
  84. prim_val fast_input :
  85.   in_channel -> string -> int -> int -> int = 4 "input";
  86. prim_val fast_output :
  87.   out_channel -> string -> int -> int -> unit = 4 "output";
  88.  
  89. fun caml_open_in_gen mode rights filename =
  90.   open_descriptor_in (sys_open filename mode rights)
  91. ;
  92.  
  93. val caml_open_in = caml_open_in_gen [O_RDONLY, O_TEXT] 0
  94. and caml_open_in_bin = caml_open_in_gen [O_RDONLY, O_BINARY] 0
  95. ;
  96.  
  97. fun open_out_gen mode rights filename =
  98.   open_descriptor_out(sys_open filename mode rights)
  99. ;
  100.  
  101. prim_val s_irall : file_perm = 0 "s_irall";
  102. prim_val s_iwall : file_perm = 0 "s_iwall";
  103.  
  104. val caml_open_out =
  105.   open_out_gen [O_WRONLY, O_TRUNC, O_CREAT, O_TEXT] (s_irall + s_iwall)
  106. and caml_open_out_bin =
  107.   open_out_gen [O_WRONLY, O_TRUNC, O_CREAT, O_BINARY] (s_irall + s_iwall)
  108. ;
  109.  
  110. prim_val caml_flush : out_channel -> unit = 1 "flush"
  111.         (* Flush the buffer associated with the given output channel,
  112.            performing all pending writes on that channel.
  113.            Interactive programs must be careful about flushing [std_out]
  114.            at the right times. *)
  115.  
  116. fun caml_output_string channel s =
  117.   fast_output channel s 0 (size s)
  118. ;
  119.  
  120. prim_val caml_close_out : out_channel -> unit = 1 "close_out"
  121.         (* Close the given channel, flushing all buffered write operations.
  122.        The behavior is unspecified if any of the above functions is
  123.        called on a closed channel. *)
  124.  
  125. fun open_in s =
  126.   ref {closed=false, ic=caml_open_in s}
  127.   handle Io _ =>
  128.     raise Io ("Cannot open "^s)
  129. ;
  130.  
  131. fun open_in_bin s =
  132.   ref {closed=false, ic=caml_open_in_bin s}
  133.   handle Io _ =>
  134.     raise Io ("Cannot open "^s)
  135. ;
  136.  
  137. fun try_input_char_ ic =
  138.   SOME (input_char_ ic)
  139.   handle Size => NONE
  140. ;
  141.  
  142. fun inputc (is as ref {closed, ic}) n =
  143.   if closed orelse n<=0 then "" else
  144.   let
  145.     val buff = create_string_ n
  146.     fun loop k =
  147.       if k = n then buff
  148.       else
  149.         case fast_input ic buff k (n-k) of
  150.             0 => sub_string_ buff 0 k
  151.           | m => loop (k+m)
  152.   in loop 0 end
  153. ;
  154.  
  155. fun input (is, n) = inputc is n;
  156.  
  157. fun lookahead (is as ref {closed, ic}) =
  158.   if closed then "" else
  159.   let val pos = caml_pos_in ic in
  160.     case try_input_char_ ic of
  161.         NONE   => ""
  162.       | SOME c =>
  163.           let val () = caml_seek_in ic pos
  164.               val s = create_string_ 1
  165.           in set_nth_char_ s 0 c; s end
  166.   end
  167. ;
  168.  
  169. fun close_in (is as ref {closed, ic}) =
  170.   if closed then () else
  171.     (caml_close_in ic;
  172.      is := { closed=true, ic=ic };
  173.      ())
  174. ;
  175.  
  176. fun end_of_stream is = (lookahead is = "");
  177.  
  178. fun open_out s =
  179.   ref {closed=false, oc=caml_open_out s}
  180.   handle Io _ =>
  181.     raise Io ("Cannot open "^s)
  182. ;
  183.  
  184. fun open_out_bin s =
  185.   ref {closed=false, oc=caml_open_out_bin s}
  186.   handle Io _ =>
  187.     raise Io ("Cannot open "^s)
  188. ;
  189.  
  190. fun outputc (os as ref {closed, oc}) s =
  191.   if closed then
  192.     raise Io "Output stream is closed"
  193.   else
  194.     (caml_output_string oc s;
  195.      if os = std_err then caml_flush oc else ())
  196. ;
  197.  
  198. fun output (os, s) = outputc os s;
  199.  
  200. fun close_out (os as ref {closed, oc}) =
  201.   if closed then () else
  202.     (caml_close_out oc; os := {closed = true, oc=oc}; ())
  203. ;
  204.  
  205. fun flush_out (os as ref {closed, oc}) =
  206.   if closed then
  207.     raise Io "Output stream is closed"
  208.   else
  209.     caml_flush oc
  210. ;
  211.  
  212. fun input_line (is as ref {closed, ic}) =
  213.   if closed then "" else
  214.   let val max = ref 127
  215.       val tmp = ref (create_string_ (!max))
  216.       fun realloc () =
  217.       let val newmax = 2 * !max
  218.           val newtmp = create_string_ newmax
  219.       in 
  220.           blit_string_ (!tmp) 0 newtmp 0 (!max);
  221.           max := newmax;
  222.           tmp := newtmp
  223.       end
  224.       fun h len =
  225.       case try_input_char_ ic of
  226.           NONE   => sub_string_ (!tmp) 0 len
  227.         | SOME c => (if len >= !max then realloc () else ();
  228.              set_nth_char_ (!tmp) len c;
  229.              if c = #"\n" then sub_string_ (!tmp) 0 (len+1) 
  230.                           else h (len+1))
  231.   in h 0 end;
  232.  
  233. fun can_inputc (is as ref {closed, ic}) n =
  234.   if n<0 then false else
  235.   if closed then n=0 else
  236.   let
  237.     val pos = caml_pos_in ic
  238.     val buff = create_string_ n
  239.     val n' = fast_input ic buff 0 n
  240.   in caml_seek_in ic pos; n' = n end
  241. ;
  242.  
  243. fun can_input (is, n) = can_inputc is n;
  244.  
  245. fun open_append s =
  246.   ref { closed=false,
  247.         oc=open_out_gen [O_WRONLY, O_APPEND, O_CREAT, O_TEXT]
  248.                         (s_irall + s_iwall) s }
  249.   handle Io _ =>
  250.     raise Io ("Cannot open "^s)
  251. ;
  252.  
  253. prim_val sys_exit : int -> 'a = 1 "sys_exit";
  254.  
  255. fun exit n =
  256.   (flush_out std_out; flush_out std_err; sys_exit n)
  257. ;
  258.  
  259. fun say s = (outputc std_out s; flush_out std_out);
  260.